package com.reebake.ideal.exception;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Locale;

/**
 * 基础异常类，增加对多语言的支持
 */
public class BaseException extends RuntimeException {
    /**
     * 默认消息
     */
    private static final String DEFAULT_MESSAGE = "exception...";
    /**
     * 默认错误码
     */
    private static final String DEFAULT_CODE = "999999";
    /**
     * 错误码
     */
    private final Integer code;
    /**
     * 参数
     */
    private final Object[] params;

    public BaseException() {
        super(DEFAULT_MESSAGE);
        this.code = null;
        this.params = null;
    }

    public BaseException(Integer code, Object... params) {
        super(DEFAULT_MESSAGE);
        this.code = code;
        this.params = params;
    }

    private String getExceptionName() {
        String name = this.getClass().getSimpleName();
        return StrUtil.removeSuffix(StrUtil.lowerFirst(name), "Exception");
    }

    public String getMessageKey() {
        String name = getExceptionName();
        return "Exception." + name;
    }

    private static HttpServletRequest getRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return ObjUtil.isNull(requestAttributes) ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
    }

    public Locale getLocale() {
        HttpServletRequest request = getRequest();
        if(ObjectUtil.isNull(request)) {
            return LocaleContextHolder.getLocale();
        }
        return request.getLocale();
    }

    public Integer getCode() {
        if(this.code != null) {
            return this.code;
        }
        String messageKey = getMessageKey() + ".code";
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        String codeStr = messageSource.getMessage(messageKey, null, DEFAULT_CODE, getLocale());
        if(StrUtil.isBlank(codeStr)) {
            return null;
        }
        return Integer.valueOf(codeStr);
    }

    @Override
    public String getLocalizedMessage() {
        String messageKey = getMessageKey() + ".message";
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        return messageSource.getMessage(messageKey, this.params, getExceptionName(), getLocale());
    }

    @Override
    public String getMessage() {
        return getLocalizedMessage();
    }

}
